package net.net23.sysdent.server.servlet;

import java.io.IOException;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.net23.sysdent.server.jdo.control.LinkController;
import net.net23.sysdent.server.jdo.control.TagController;
import net.net23.sysdent.server.jdo.control.UserController;
import net.net23.sysdent.server.jdo.pojos.Link;
import net.net23.sysdent.server.jdo.pojos.Tag;
import net.net23.sysdent.server.jdo.pojos.User;
import net.net23.sysdent.server.servlet.xmpp.XMPPMessage;

import com.google.appengine.api.xmpp.JID;
import com.google.appengine.api.xmpp.Message;
import com.google.appengine.api.xmpp.MessageBuilder;
import com.google.appengine.api.xmpp.SendResponse;
import com.google.appengine.api.xmpp.XMPPService;
import com.google.appengine.api.xmpp.XMPPServiceFactory;

public class XMPPReceiverServlet extends HttpServlet {

	private static final long serialVersionUID = -805316061444444353L;

	private static final Logger log = Logger
			.getLogger(XMPPReceiverServlet.class.getName());

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		XMPPMessage xmppMsg = new XMPPMessage(req);
		try {
			User user = UserController.forceUserByMail(xmppMsg.getEmailFrom());
			if (user.isActive()) {
				switch (xmppMsg.getType()) {
				case XMPPMessage.NULL:
					break;
				case XMPPMessage.LINK:
					saveLink(xmppMsg, user);
					break;
				case XMPPMessage.QUERY_BY_TEXT:
					sendMessage(xmppMsg.getFromJid(),
							searchLinks4Chat(user, xmppMsg.getPlainText()));
					break;
				case XMPPMessage.ADD_TAG:
					saveTag(xmppMsg, user);
					break;
				default:
					sendMessage(xmppMsg.getFromJid(), "Se fue por default. :-X");
					break;
				}
			} else {
				sendMessage(xmppMsg.getFromJid(),
						"Tu usuario seencuentra inactivo. :-X");
			}
		} catch (Exception e) {
			sendMessage(xmppMsg.getFromJid(), e.getMessage());
		}
	}

	private String searchLinks4Chat(User user, String plainText) {
		List<Link> linksByCriteria = LinkController.getLinksByCriteria(
				user.getId(), plainText, 0, 5);
		if (linksByCriteria.isEmpty()) {
			return ":( [No se encontraron resultados]";
		}
		StringBuilder results = new StringBuilder();
		for (Link link : linksByCriteria) {
			results.append(link.getLink()).append("\n");
		}
		return results.toString();
	}

	private void saveTag(XMPPMessage xmppMsg, User user) {
		Tag _tag = TagController.forceTagByNameAndUser(xmppMsg.getPlainText(),
				user.getId());
		if (_tag != null) {
			sendOkMessage(xmppMsg);
		} else {
			sendErrorMessage(xmppMsg);
		}
	}

	private void sendErrorMessage(XMPPMessage xmppMsg) {
		sendMessage(xmppMsg.getFromJid(), ":(");
	}

	private void sendOkMessage(XMPPMessage xmppMsg) {
		sendMessage(xmppMsg.getFromJid(), ":)");
	}

	private void saveLink(XMPPMessage xmppMsg, User user) {
		Link _link = LinkController.forceByUserAndLink(user.getId(),
				xmppMsg.getBody());
		if (_link != null) {
			sendOkMessage(xmppMsg);
		} else {
			sendErrorMessage(xmppMsg);
		}
	}

	/**
	 * This method let us send a chat message to jid user.
	 * 
	 * @param jid
	 *            jid user
	 * @param msgBody
	 *            message contents
	 */
	private void sendMessage(JID jid, String msgBody) {
		Message msg = new MessageBuilder().withRecipientJids(jid)
				.withBody(msgBody).build();
		boolean messageSent = false;
		XMPPService xmpp = XMPPServiceFactory.getXMPPService();
		if (xmpp.getPresence(jid).isAvailable()) {
			SendResponse status = xmpp.sendMessage(msg);
			messageSent = (status.getStatusMap().get(jid) == SendResponse.Status.SUCCESS);
		}
		if (!messageSent) {
			log.log(Level.SEVERE, "No se pudo enviar el mensaje (" + msgBody
					+ ") a " + jid.getId());
		}
	}
}
